/******************************************************************************* 
  Copyright (C), 1988-2020, zeno Tech. Co., Ltd.
  Description:   queue模块  
  Function List:     
  History:
    <wangmc -- 2015-08-04>  创建
*******************************************************************************/ 

/*=============================================================================
                                 Includes                                  
 =============================================================================*/
#include "aacPriv.h"

/*=============================================================================
                               Macro Definition
 =============================================================================*/

/*=============================================================================
                        Local Structures and Typedef 
 =============================================================================*/
/* queue控制结构体 */
typedef struct   
{  
    void *pBase;  
    int dataSize;               /* 单元数据长度 */
    int front;                  /* 指向队列第一个元素 */  
    int rear;                   /* 指向队列最后一个元素的下一个元素 */  
    int maxsize;                /* 循环队列的最大存储空间 */ 
    pthread_mutex_t queueMutex; /* queue多线程操作线程锁 */
}QUEUE_ctl_t; 

/*=============================================================================
                             Extern Variables                                  
=============================================================================*/


/*=============================================================================
                             Local Variables                                  
 =============================================================================*/


/*=============================================================================
                             Function Definition                                  
 =============================================================================*/
/*******************************************************************************
    Function:     AUDIO_QueueCreate
    Description:  创建队列
    Input:        - maxsize: 队列缓存元素个数
                  - dataSize: 单元数据长度
    Output:       无
    Return:       !NULL: 操作成功
                  NULL: 操作失败
    Others:       无
*******************************************************************************/
void *AUDIO_QueueCreate(int maxsize, int dataSize)  
{  
    QUEUE_ctl_t *pQueueCtl = NULL;

    pQueueCtl = (QUEUE_ctl_t *)malloc(sizeof(QUEUE_ctl_t));
    if (!pQueueCtl)
    {
        LOG_PrintError("Fail to malloc queue ctl!\n");
        return NULL;
    }

    memset(pQueueCtl, 0, sizeof(QUEUE_ctl_t));

    pQueueCtl->pBase = malloc(dataSize * maxsize);  
    if(!pQueueCtl->pBase)  
    {  
        LOG_PrintError("Fail to malloc queue ctl!\n");
        goto free_buf;
    }  
    
    pQueueCtl->front = 0;
    pQueueCtl->rear = 0;
    pQueueCtl->maxsize = maxsize;
    pQueueCtl->dataSize = dataSize;

    pthread_mutex_init(&pQueueCtl->queueMutex, NULL);

    return (void *)pQueueCtl;

free_buf:
    free(pQueueCtl);
    return NULL;
}

/*******************************************************************************
    Function:     AUDIO_QueueDestroy
    Description:  销毁队列
    Input:        - hQueue: 队列句柄
    Output:       无
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
int AUDIO_QueueDestroy(void *hQueue)
{
    QUEUE_ctl_t *pQueueCtl = NULL;

    pQueueCtl = (QUEUE_ctl_t *)hQueue;

    free(pQueueCtl->pBase);
    pQueueCtl->maxsize = 0;
    pQueueCtl->front = 0;
    pQueueCtl->rear = 0;
    pQueueCtl->dataSize = 0;

    pthread_mutex_destroy(&pQueueCtl->queueMutex);

    free(pQueueCtl);

    return 0;
}

/*******************************************************************************
    Function:     AUDIO_QueueIsFull
    Description:  判断队列是否已满
    Input:        - pQueueCtl: 队列控制结构体指针
    Output:       无
    Return:       0: 未满
                  1: 已满
    Others:       无
*******************************************************************************/
static int AUDIO_QueueIsFull(QUEUE_ctl_t *pQueueCtl)  
{  
    if(pQueueCtl->front == (pQueueCtl->rear + 1)%pQueueCtl->maxsize)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}  

/*******************************************************************************
    Function:     AUDIO_QueueIsEmpty
    Description:  判断队列是否为空
    Input:        - pQueueCtl: 队列控制结构体指针
    Output:       无
    Return:       0: 未空
                  1: 已空
    Others:       无
*******************************************************************************/
static int AUDIO_QueueIsEmpty(QUEUE_ctl_t *pQueueCtl)  
{  
    if(pQueueCtl->front == pQueueCtl->rear)
    {
        return 1;
    }
    else 
    {
        return 0;
    }
}  

/*******************************************************************************
    Function:     AUDIO_QueueState
    Description:  查询队列状态
    Input:        - hQueue: 队列句柄
    Output:       无
    Return:       0 : 正常
                  -1: 队列已满
                  1 : 队列为空
    Others:       无
*******************************************************************************/
int AUDIO_QueueState(void *hQueue)
{
    int ret = 0;
    QUEUE_ctl_t *pQueueCtl = NULL;

    pQueueCtl = (QUEUE_ctl_t *)hQueue;
    
    pthread_mutex_lock(&pQueueCtl->queueMutex);
    
    if(AUDIO_QueueIsFull(pQueueCtl) == 1)
    {
        ret = -1; 
    }
    else if(AUDIO_QueueIsEmpty(pQueueCtl) == 1)
    {
        ret = 1;
    }

    pthread_mutex_unlock(&pQueueCtl->queueMutex);

    return ret;
}

/*******************************************************************************
    Function:     AUDIO_QueueWriteData
    Description:  向队列写入数据
    Input:        - hQueue: 队列句柄
                  - pData: 流媒体结构体指针
    Output:       无
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
int AUDIO_QueueWriteData(void *hQueue, void *pData)  
{  
    int ret;
    QUEUE_ctl_t *pQueueCtl = NULL;

    pQueueCtl = (QUEUE_ctl_t *)hQueue;
    
    pthread_mutex_lock(&pQueueCtl->queueMutex);
    
    if(AUDIO_QueueIsFull(pQueueCtl) == 1)
    {
        ret = -1; 
    }
    else  
    {  
        memcpy((void *)((unsigned int)pQueueCtl->pBase + pQueueCtl->rear*pQueueCtl->dataSize),
                (const void *)pData, 
                pQueueCtl->dataSize);
        pQueueCtl->rear = (pQueueCtl->rear + 1)%pQueueCtl->maxsize;  
        ret = 0;  
    } 

    pthread_mutex_unlock(&pQueueCtl->queueMutex);

    return ret;
}  

/*******************************************************************************
    Function:     AUDIO_QueueReadData
    Description:  从队列读出数据
    Input:        - hQueue: 队列句柄
                  - pData: 流媒体结构体指针
    Output:       无
    Return:       0: 操作成功
                  -1: 操作失败
    Others:       无
*******************************************************************************/
int AUDIO_QueueReadData(void *hQueue, void *pData)  
{  
    int ret;  
    QUEUE_ctl_t *pQueueCtl = NULL;

    pQueueCtl = (QUEUE_ctl_t *)hQueue;

    if (!pQueueCtl || !pData)
    {
        LOG_PrintError("pQueueCtl or pAencStream is NULL.\n");
        return -1;
    }
    
    pthread_mutex_lock(&pQueueCtl->queueMutex);
    
    if(AUDIO_QueueIsEmpty(pQueueCtl) == 1)  
    {  
        ret = -1;  
    }  
    else  
    {  
        memcpy(pData, 
                (const void *)((unsigned int)pQueueCtl->pBase + pQueueCtl->front*pQueueCtl->dataSize),
                pQueueCtl->dataSize);
        pQueueCtl->front = (pQueueCtl->front + 1)%pQueueCtl->maxsize;  
        ret = 0;  
    }  

    pthread_mutex_unlock(&pQueueCtl->queueMutex);

    return ret;
}  
